package com.bankcomm.ui.views;

import com.bankcomm.ui.views.VerticalSlidingMenu.OnMenuListener;

import android.content.Context;
import android.graphics.Canvas;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.Scroller;


public class VerticalSlidingView extends LinearLayout  {
	private Scroller mScroller;
	private VelocityTracker mVelocityTracker;
	private int mTouchSlop;
	
	// �����������ͼ
	private View mMenuView;
	// �Ź�����ײ��˵���ͼ
	private View mMainView;
	
	private LinearLayout llinner;
	private FrameLayout menuLayout;
	private FrameLayout mainLayout;
	
	private OnMenuListener listener;
	
	private float mLastMotionX;
	private float mLastMotionY;
	
	private int mMenuHeight_;
	
	private static final int SNAP_VELOCITY = 1000;
	
	public VerticalSlidingView(Context context) {
		super(context);
		init();
	}
	
	public VerticalSlidingView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}
	
	public void init(){
		mScroller = new Scroller(getContext());
		mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
	}
	
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		final int width = r - l;
		final int height = b - t;
		llinner.layout(0, 0, width, height);
	}
	
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		llinner.measure(widthMeasureSpec, heightMeasureSpec);
	}

	public void setMenuView(View v){
		if (menuLayout.getChildCount() > 0) {
			menuLayout.removeAllViews();
		}
		this.mMenuView = v;
		menuLayout.addView(v);
	}
	
	public void setMainView(View v){
		if (mainLayout.getChildCount() > 0) {
			mainLayout.removeAllViews();
		}
		this.mMainView = v;
		mainLayout.addView(v);
	}
	
	@Override
	public void scrollTo(int x, int y) {
		super.scrollTo(x, y);
		postInvalidate();
	}
	
	@Override
	public void computeScroll() {
		if (!mScroller.isFinished()) {
			if (mScroller.computeScrollOffset()) {
				int oldX = getScrollX();
				int oldY = getScrollY();
				int x = mScroller.getCurrX();
				int y = mScroller.getCurrY();
				if (oldX != x || oldY != y) {
					scrollTo(x, y);
				}
				// Keep on drawing until the animation has finished.
				invalidate();
			} else {
				clearChildrenCache();
			}
		} else {
			clearChildrenCache();
		}
	}
	
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
	}
	
	// ��ȡllinner�߶�
	public void getMenuViewHeight(int height) {
		mMenuHeight_ = height;
	}
	
	public void setListener(OnMenuListener listener) {
		this.listener = listener;
	}
	
	/**
	 * ��ʾView������
	 * */
	public void showTopView() {
		
		int menuHeight = mMenuView.getHeight();
		int oldScrollY = getScrollY();
		if (oldScrollY == 0) {
			BCMHomeView.isOpen = false;
			smoothScrollTo(menuHeight);
		} else if (oldScrollY == menuHeight) {
			BCMHomeView.isOpen = true;
			smoothScrollTo(-menuHeight);
		}
		if(null != listener){
			listener.openMenu(BCMHomeView.isOpen);
		}	
	}
	
	void smoothScrollTo(int dY) {
		int duration = 800;
		int oldScrollY = getScrollY();
		mScroller.startScroll(getScrollX(), oldScrollY, getScrollX(), dY,duration);
		invalidate();
	}

	void enableChildrenCache() {
		final int count = getChildCount();
		for (int i = 0; i < count; i++) {
			final View layout = (View) getChildAt(i);
			layout.setDrawingCacheEnabled(true);
		}
	}

	void clearChildrenCache() {
		final int count = getChildCount();
		for (int i = 0; i < count; i++) {
			final View layout = (View) getChildAt(i);
			layout.setDrawingCacheEnabled(false);
		}
	}
	
	// ����llinner����
	public void setLLinnerParams() {
		LayoutParams llinner_lp = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
		llinner = new LinearLayout(getContext());
		llinner.setOrientation(LinearLayout.VERTICAL);
		
		this.addView(llinner, llinner_lp);
		
		LayoutParams lp = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
		menuLayout = new FrameLayout(getContext());
		
		llinner.addView(menuLayout, lp);
		
		lp = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
		mainLayout = new FrameLayout(getContext());
		llinner.addView(mainLayout, lp);
		this.invalidate();
	}

	private boolean mIsBeingDragged;
	boolean isCanScroll = true;
	boolean isTouchSlop = false;
	
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		if(!isCanScroll){
			return false;
		}
		final int action = ev.getAction();
		final float x = ev.getX();
		final float y = ev.getY();
		final int oldScrollY = getScrollY();

		switch (action) {
		case MotionEvent.ACTION_DOWN:
			mLastMotionX = x;
			mLastMotionY = y;
			mIsBeingDragged = false;
			break;
		case MotionEvent.ACTION_MOVE:
			final float dx = x - mLastMotionX;
			final float dy = y - mLastMotionY;
			final float xDiff = Math.abs(dx);
			final float yDiff = Math.abs(dy);
			
			if ((oldScrollY == mMenuHeight_ && dy < 0) || (oldScrollY == 0 && dy >= 0)) {
				this.requestFocus();
				mainLayout.requestFocus();
				mainLayout.onTouchEvent(ev);
				return false;
			}
			
			if (yDiff > mTouchSlop && xDiff < yDiff) {
				mIsBeingDragged = true;
				mLastMotionY = y;
			}
			break;
			
		}
		return mIsBeingDragged;
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		mIsBeingDragged = true;
		if (mVelocityTracker == null) {
			mVelocityTracker = VelocityTracker.obtain();
		}
		mVelocityTracker.addMovement(ev);

		final int action = ev.getAction();
		final float x = ev.getX();
		final float y = ev.getY();

		switch (action) {
		case MotionEvent.ACTION_DOWN:
			if (!mScroller.isFinished()) {
				mScroller.abortAnimation();
			}
			mLastMotionX = x;
			mLastMotionY = y;
			if (getScrollY() == 0) {
				return false;
			}
			break;
		case MotionEvent.ACTION_MOVE:
			if (mIsBeingDragged) {
				enableChildrenCache();
				final float deltaY = mLastMotionY - y;
				mLastMotionY = y;
				float oldScrollY = getScrollY();
				float scrollY = oldScrollY + deltaY;

				// ��� deltaY ��������oldScrollY���������������죬
				// ������������
				if (deltaY > 0 && oldScrollY > 0) {
					final float topBound = 0;
					final float bottomRound = mMenuHeight_;
					if (scrollY <= topBound) {
						scrollY = topBound;
					} else if (scrollY > bottomRound) {
						scrollY = bottomRound;
					}
				}

				if(scrollY <= 0){
					scrollY = 0;
				}
				
				scrollTo(getScrollX(),(int) scrollY);
			}
			break;
		case MotionEvent.ACTION_CANCEL:
		case MotionEvent.ACTION_UP:
			if (mIsBeingDragged) {
				final VelocityTracker velocityTracker = mVelocityTracker;
				velocityTracker.computeCurrentVelocity(800);
				int velocityY = (int) velocityTracker.getYVelocity();
				velocityY = 0;
				int oldScrollY = getScrollY();
				int dy = 0;
				
				if (oldScrollY == 0) {
					showView(true);
				} else 
				if (oldScrollY > 0) {
					if (oldScrollY > mMenuHeight_ / 2
							|| velocityY > SNAP_VELOCITY) {
						if (oldScrollY > mMenuHeight_) {
							dy = oldScrollY - mMenuHeight_;
						} else {
							dy = mMenuHeight_ - oldScrollY;
						}
						
						showView(false);
					} else if (oldScrollY <= mMenuHeight_ / 2
							|| velocityY < -SNAP_VELOCITY) {
						dy = -oldScrollY;
						
						showView(true); 
					}
				}
				
				smoothScrollTo(dy);
				clearChildrenCache();
			}

			break;

		}
		if (mVelocityTracker != null) {
			mVelocityTracker.recycle();
			mVelocityTracker = null;
		}

		return true;
	}
	
	private void showView(boolean open){
		Message msg = new Message();
		msg.obj = open;
		BCMHomeView.handler.sendMessage(msg);
	}
	
}
